#pragma once
/**************************************************************************
    Copyright [2011] www.flycode.org
    Author:rangerlee
    EMail:rangerlee@foxmail.com
    This file is part of Alleria project

***************************************************************************/
#include <map>
#include <string>

class CDynCreatable;

class CRuntimeClass
{
public:
	typedef CDynCreatable* (*PCreateObjectEntry)();
	LPCTSTR m_szClassName;
	PCreateObjectEntry m_pfnCreateObject;
	CDynCreatable *CreateObject();
};

class CClassCollection
{
public:
	static CDynCreatable * CreateFromName(LPCTSTR szClassName)
	{
		if ( m_pClassMap )
		{
			ClassMapRuntimeClass::const_iterator it = m_pClassMap->find(szClassName);
			if ( it != m_pClassMap->end() )
			{
				return it->second->CreateObject();
			}
		}
		return NULL;
	}

	static void AddClass(LPCTSTR szClassName, CRuntimeClass *pRuntimeClass)
	{
		if ( !m_pClassMap )
		{
			m_pClassMap = new ClassMapRuntimeClass();
		}
		(*m_pClassMap)[szClassName] = pRuntimeClass;
	}

private:
	typedef std::map<std::string, CRuntimeClass *> ClassMapRuntimeClass;
	static ClassMapRuntimeClass *m_pClassMap;
};

class CIavpDynCreatable
{
public:
	CIavpDynCreatable() {}
	virtual ~CIavpDynCreatable() = 0
	{}
	virtual CRuntimeClass * GetRuntimeClass() const = 0;
	static CDynCreatable * CreateFromName(LPCTSTR szClassName)
	{
		return CClassCollection::CreateFromName(szClassName);
	}
};


#define RUNTIME_CLASS(ClassName) ((CRuntimeClass *)(&ClassName::class##ClassName))

#define DECLARE_DYNCREATE(ClassName) \
public:\
		   static CDynCreatable * CreateObject();   \
		   static CRuntimeClass::PCreateObjectEntry GetCreateObjectEntry();  \
		   virtual CRuntimeClass * GetRuntimeClass() const;    \
		   const static CRuntimeClass class##ClassName;

#define IMPLEMENT_DYNCREATE(ClassName)  \
	   CDynCreatable * ClassName::CreateObject()    \
	   { return new ClassName(); } \
	   CRuntimeClass::PCreateObjectEntry ClassName::GetCreateObjectEntry()  \
	   {CClassCollection::AddClass(#ClassName, RUNTIME_CLASS(ClassName)); return ClassName::CreateObject;}   \
	   CRuntimeClass * ClassName::GetRuntimeClass() const \
	   {return RUNTIME_CLASS(ClassName);}   \
	   const CRuntimeClass ClassName::class##ClassName =  \
	   {#ClassName, ClassName::GetCreateObjectEntry()};

	   CDynCreatable *CRuntimeClass::CreateObject()
	   {
		   return (*m_pfnCreateObject)();
	   }

//----------------------------------------------------------------------------------

enum EProtocolLine
{
	h_Unknow,
	h_Method,
	h_Session,
	h_Time,
	h_Auth,
	h_From,
	h_To,
	h_Context,
	h_Tail,
};

class CProtocolMsg
{
public:
	CProtocolMsg(void);
	~CProtocolMsg(void);

	std::string Header(EProtocolLine h_Line) const;

private:
	std::map<std::string,std::string> m_aMsg;
};

